package prefix.platform.loan;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

import prefix.loan.util.LoanMaturity;
import service.LoanAppService;

public enum LoanClass {

    // Loan Classes (AA loan grades are intentionally out of the fico score

    A1("A1", LoanGrade.A, 6, 780, 900, true),
    A2("A2", LoanGrade.A, 7, 750, 780, true),
    A3("A3", LoanGrade.A, 8, 734, 750, true),
    A4("A4", LoanGrade.A, 9, 723, 734, true),
    A5("A5", LoanGrade.A, 10, 714, 723, true),

    B1("B1", LoanGrade.B, 11, 707, 714, true),
    B2("B2", LoanGrade.B, 12, 700, 707, true),
    B3("B3", LoanGrade.B, 13, 693, 700, true),
    B4("B4", LoanGrade.B, 14, 686, 693, true),
    B5("B5", LoanGrade.B, 15, 679, 686, true),

    C1("C1", LoanGrade.C, 16, 675, 679, true),
    C2("C2", LoanGrade.C, 17, 671, 675, true),
    C3("C3", LoanGrade.C, 18, 668, 671, true),
    C4("C4", LoanGrade.C, 19, 664, 668, true),
    C5("C5", LoanGrade.C, 20, 660, 664, true),

    D1("D1", LoanGrade.D, 21, 656, 660, true),
    D2("D2", LoanGrade.D, 22, 652, 656, true),
    D3("D3", LoanGrade.D, 23, 648, 652, true),
    D4("D4", LoanGrade.D, 24, 644, 648, true),
    D5("D5", LoanGrade.D, 25, 640, 644, true),

    E1("E1", LoanGrade.E, 26, 638, 640, true),
    E2("E2", LoanGrade.E, 27, 635, 638, true),
    E3("E3", LoanGrade.E, 28, 632, 635, true),
    E4("E4", LoanGrade.E, 29, 629, 632, true),
    E5("E5", LoanGrade.E, 30, 627, 629, true),

    F1("F1", LoanGrade.F, 31, 624, 627, true),
    F2("F2", LoanGrade.F, 32, 621, 624, true),
    F3("F3", LoanGrade.F, 33, 617, 621, true),
    F4("F4", LoanGrade.F, 34, 615, 617, true),
    F5("F5", LoanGrade.F, 35, 614, 615, true),

    G1("G1", LoanGrade.G, 36, 612, 614, false),
    G2("G2", LoanGrade.G, 37, 610, 612, false),
    G3("G3", LoanGrade.G, 38, 608, 610, false),
    G4("G4", LoanGrade.G, 39, 606, 608, false),
    G5("G5", LoanGrade.G, 40, 604, 606, false);

    // -----------------------------------------------------------------------------------------------------
    // -----------------------------------------------------------------------------------------------------
    // -----------------------------------------------------------------------------------------------------
    // -----------------------------------------------------------------------------------------------------
    // ------------ Init Methods

    public static void main(String[] args) {
        //

        LoanClass[] lc = LoanClass.values();
        for (LoanClass l : lc) {
            System.out.println("--Name:" + l.name() + " --Interest: " + l.getApr() + " --grade:" + l.g.name());
        }
    }

    private final LoanGrade g; // A,B,C,D

    private final String cn; // A,B,C,D

    private final int sg; // 11.... ,21....,

    private final double RATE; // Intrest rate [0..1], 0.075 means 7.5%

    private final int fmin; // min FICO per this band

    private final int fmax; // max FICO per this band

    private double origFee; // origination fees

    private double serviceFee; // service fees

    private double managementFee;// management fee

    private boolean enabled = false;

    private LoanClass(String name, LoanGrade grade, int subGrade, int minFico, int maxFico, boolean enabled) {
        this.cn = name;
        this.sg = subGrade;
        this.g = grade;

        this.RATE = Params.SL_INT_RATE[subGrade - 1];

        this.fmin = minFico; // min fico score
        this.fmax = maxFico; // max fico score

        this.serviceFee = ServiceFees.SL_SERVICE_FEE[subGrade - 1];
        this.managementFee = ServiceFees.SL_MANAGEMENT_FEE[subGrade - 1];
        this.origFee = ServiceFees.SL_ORIG_FEE[subGrade - 1];

        this.enabled = enabled;
    }

    // ----------------------------------------------------------------------------------------------
    // Per class getters
    // ----------------------------------------------------------------------------------------------
    public int getSubGrade() {
        return this.sg;
    }

    public LoanGrade getGrade() {
        return this.g;
    }

    public String getClassName() {
        return this.cn;
    }

    public double getApr() {
        return this.RATE;
    }

    public int getMinFico() {
        return this.fmin;
    }

    public int getMaxFico() {
        return this.fmax;
    }

    public boolean isEnabled() {
        return this.enabled;
    }

    public double getRATE() {
        return RATE;
    }

    public int getSg() {
        return sg;
    }

    public double classServiceFee(LoanMaturity maturity) {
        // switch(maturity) {
        // case Year3: return this.sFee3Year;
        // case Year5: return this.sFee5Year;
        // }
        return this.serviceFee;
    }

    // ----------------------------------------------------------------------------------------------

    public double getOriginationFeeRate() {
       return this.origFee;
    }

    public double getListedOriginationFee(double amount, LoanAppService app, LoanMaturity mat) {
        // double origFee = Math.max(TLCConstants.MinOriginatioinFee,
        // amount*getSLOriginationFeeRate(app,mat));
        // double fee = TLCUtil.round2Decimal(origFee).doubleValue();
        // return fee;

        return 0;
    }

    // --------------------------------------------------------------------------------------------------------------------

    // --------------------------------------------------------------------------------------------------------------------

    public static LoanClass getLoanClassBysubGrade(int subgrade) {
        for (LoanClass lc : LoanClass.values()) {
            if (lc.getSubGrade() == subgrade)
                return lc;
        }
        return null;
    }

    public static LoanClass getLoanClassByName(String name) {
        for (LoanClass lc : LoanClass.values()) {
            if (StringUtils.equals(name, lc.cn))
                return lc;
        }
        return null;
    }



    public double getServiceFeeRate() {
        return serviceFee;
    }

    public double getManagementFeeRate() {
        return managementFee;
    }

    /**
     * Get enabled loan classes
     */
    public static List<LoanClass> getEnabledClasses() {
        List<LoanClass> enabledClasses = new ArrayList<LoanClass>();
        for (LoanClass c : LoanClass.values()) {
            if (c.isEnabled()) {
                enabledClasses.add(c);
            }
        }
        return enabledClasses;
    }

    /**
     * Get the loan class with the minimum APR rate
     */
    public static LoanClass getMinRateClass() {
        LoanClass min = null;
        for (LoanClass c : LoanClass.values()) {
            if (c.isEnabled() && (min == null || c.getApr() < min.getApr())) {
                min = c;
            }
        }
        return min;
    }

    /**
     * Get the loan class with the maximum APR rate
     */
    public static LoanClass getMaxRateClass() {
        LoanClass max = null;
        for (LoanClass c : LoanClass.values()) {
            if (c.isEnabled() && (max == null || c.getApr() > max.getApr())) {
                max = c;
            }
        }
        return max;
    }
}
